using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Reflection;
using UnityEditor;

public static class DrawUtil 
{
    public static void DrawObject(object obj)
    {
        var type = obj.GetType();
        var fieldList = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
        foreach(var field in fieldList) 
        {
            DrawFieldWithColor(obj, field);
        }
    }

    public static void DrawFieldWithColor(object obj, FieldInfo field)
    {
        ProcessFieldColor(obj, field, () =>
        {
            DrawField(obj, field);
        });
    }

    static void DrawField(object obj, FieldInfo field)
    {
        var fieldType = field.FieldType;
        var fieldName = field.Name;
        var fieldValue = field.GetValue(obj);
        if (fieldType == typeof(string))
        {
            var strValue = fieldValue as string;
            var postValue = EditorGUILayout.TextField(fieldName, strValue);
            if(postValue != strValue)
            {
                field.SetValue(obj, postValue);
            }
        }
        else if(fieldType == typeof(bool))
        {
            var boolValue = (bool)fieldValue;
            var postValue = EditorGUILayout.Toggle(fieldName, boolValue);
            if(postValue != boolValue) 
            {
                field.SetValue(obj, postValue);
            }
        }
        else if(fieldType == typeof(int))
        {
            var intValue = (int)fieldValue;
            var postValue = EditorGUILayout.IntField(fieldName, intValue);
            if (postValue != intValue)
            {
                field.SetValue(obj, postValue);
            }
        }
        else if(fieldType.IsSubclassOf(typeof(Enum)))
        {
            var enumValue = (Enum)fieldValue;
            var postValue = EditorGUILayout.EnumPopup(fieldName, enumValue);
            if(postValue != enumValue)
            {
                field.SetValue(obj, postValue);
            }
        }
    }

    static void ProcessFieldColor(object obj, FieldInfo field, Action drawHandler)
    {
        var willChangeColor = ShouldChangeColor(obj, field);
        if (willChangeColor)
        {
            ChnageColor();
        }
        drawHandler?.Invoke();

        if (willChangeColor)
        {
            ResetColor();
        }
    }

    static bool ShouldChangeColor(object obj, FieldInfo field)
    {
        var defaultValue = TryGetDefaultValue(field);
        if (defaultValue != null)
        {
            var value = field.GetValue(obj);
            if (!value.Equals(defaultValue))
            {
                return true;
            }
        }
        return false;
    }

    static Color old;
    static void ChnageColor()
    {
        old = GUI.color;
        GUI.color = new Color(0, 1f, 0.5f);
    }

    static void ResetColor()
    {
        GUI.color = old;
    }
    public static object TryGetDefaultValue(FieldInfo field)
    {
        var attribute = field.GetCustomAttribute<DefaultValueAttribute>();
        if(attribute == null)
        {
            return null;
        }
        return attribute.value;
    }
}

